/**
 * @file s_sample.c
 * @brief 
 * @author xuesong (wenshaoliu@foxmail.com)
 * @version 1.0
 * @date 2023-12-06
 * 
 * @copyright Copyright (c) 2023  by xuesong
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2023-12-06     <td>1.0     <td>xuesong   <td>内容
 * </table>
 */

#include "s_sample.h"
#include "cs1259B.h"
#include "s_weight.h"
#include "cs1237.h"
//---------------------------------------------------------------------
#define  MID_BUF_NUM      7
typedef struct{
    uint32_t adcBuff[MID_BUF_NUM];
    uint8_t index;
}AdcBuff_t;
AdcBuff_t AdcBuff={
    .index = 0,
};
#if(USE_ADC_CHIP == CS1259B)
#define  READ_ADC_BUFF_LEN 7
#else
#define  READ_ADC_BUFF_LEN 3
#endif
typedef struct{
    uint32_t adcReadBuff[READ_ADC_BUFF_LEN];
    uint8_t index;
}readAdcBuff_t;
readAdcBuff_t ReadAdcBuff={
    .index = 0,
};
//---------------------------------------------------------------------
userAdc_t   userAdcStruct={
    .Flag.Byte = 0,
    .Adc = 0,
    .FilterAdc = 0,
};
//---------------------------------------------------------------------
uint32_t medianFilter(const uint32_t* buff,uint8_t buffLen,uint8_t index);
//---------------------------------------------------------------------
void ADC_Precss(uint8_t taskid,uint16_t eventFlag)
{
    static uint8_t adcStep = 0;
    static uint8_t readResetCnt = 0;
    static uint32_t adcSum = 0;
    uint32_t readAdcValue = 0;

    if(!userAdcStruct.Flag.Bit.init)
    {
#if(USE_ADC_CHIP == CS1259B)
        switch(adcStep)
        {
            case    0:
	                AFE_Rest_Communicate_Interface();
                    adcStep++;
                    readResetCnt = 0;
                    osal_start_timerEx(taskid, eventFlag, 5);
                    break;
            case    1:
	                AFE_ResetCmd();
                    osal_start_timerEx(taskid, eventFlag, 5);
                    readResetCnt &= 0xF0;
                    adcStep++;
                    break;
            case    2:
                    if(AFE_ReadResetStatus())
                    {
                        adcStep++;
                        osal_start_timerEx(taskid, eventFlag, 5);
                        readResetCnt = 0;
                    }else{
                        osal_start_timerEx(taskid, eventFlag, 2);
                        readResetCnt++;
                        if((readResetCnt&0x0F) > 5)
                        {
                            readResetCnt += 0x10;
                            readResetCnt &= 0xF0;
                            if(readResetCnt > 0x30)
                                adcStep = 0;
                            else
                                adcStep = 1;
                            osal_start_timerEx(taskid, eventFlag, 2);
                        }
                    }
                    break;
            case    3:
                    {
                        AFE_Reset_Next();
                        userAdcStruct.Flag.Bit.init = true;
                        userAdcStruct.Flag.Bit.CheckReg = 0;
                        adcStep = 0;
                        F_AFE_INIT();
                        CS_RegisterADTrage();
                    }
                    break;
        }
#else
        fun_1237_Init();
        userAdcStruct.Flag.Bit.init = true;
        userAdcStruct.Flag.Bit.CheckReg = 0;
        Cs1237Cofig.config = ON_ADOPTION;
        Cs1237Cofig.Flag.Bit.WriteConfig = true;
        CS_RegisterADTrage();
#endif
        // if(AFE_Reset())
        // {
        //     AFE_Reset_Next();
        //     userAdcStruct.Flag.Bit.init = true;
        //     userAdcStruct.Flag.Bit.CheckReg = 0;
        //     adcStep = 0;
        //     F_AFE_INIT();

        //     CS_RegisterADTrage();
        // }else{
        //     adcStep++;
        //     osal_start_timerEx(taskid, eventFlag, 10);
        //     LOG("reset err %d\n",adcStep);
        // }
    }
    if(userAdcStruct.Flag.Bit.AdcInterrNew){
        userAdcStruct.Flag.Bit.AdcInterrNew = false;
        CS_unRegisterADTrage();
#if(USE_ADC_CHIP == CS1259B)       
        readAdcValue = AFE_ReadAdc();
#else
        if(!Cs1237Cofig.Flag.Bit.init)
        {
            Cs1237Cofig.Flag.Bit.init = true;
            Cs1237Cofig.config = ON_ADOPTION;
            Cs1237Cofig.Flag.Bit.WriteConfig = true;
            readAdcValue = Read1237Adc(&Cs1237Cofig);
        }else{
            readResetCnt++;
            if(readResetCnt > 10)
            {
                CS1237_t tempConfig ={
                    .config = 0,
                    .Flag.Byte = 0,
                };
                readResetCnt = 0;
                readAdcValue = Read1237Adc(&tempConfig);
                // LOG("read 1237 config = 0x%X\n",tempConfig.config);
                if(tempConfig.config != Cs1237Cofig.config)
                {
                    Cs1237Cofig.Flag.Bit.init = false;          //重新配置
                    LOG("read err 1237 config = 0x%X\n",tempConfig.config);
                }
            }else{
                readAdcValue = Read1237Adc(NULL);
            }
        }
#endif

        ReadAdcBuff.adcReadBuff[ReadAdcBuff.index] = readAdcValue;
        ReadAdcBuff.index++;
        if(ReadAdcBuff.index >= READ_ADC_BUFF_LEN)
            ReadAdcBuff.index = 0;

        // LOG("Iorign=%x\n",readAdcValue);

        adcStep++;
        readAdcValue = medianFilter(ReadAdcBuff.adcReadBuff,READ_ADC_BUFF_LEN,(READ_ADC_BUFF_LEN>>1)+1);
        adcSum += readAdcValue;
#if(USE_ADC_CHIP == CS1259B)       
        if(adcStep >= 2)
        {
            userAdcStruct.Adc = adcSum/adcStep;
            userAdcStruct.Flag.Bit.adcNew = TRUE;
            adcSum = 0;
            adcStep = 0;
        }
#else
        if(adcStep >= 4)
        {
            userAdcStruct.Adc = adcSum/adcStep;
            userAdcStruct.Flag.Bit.adcNew = TRUE;
            adcSum = 0;
            adcStep = 0;
            // LOG("Iaverage=%x\n",userAdcStruct.Adc);
        }   
#endif
#if(USE_ADC_CHIP == CS1259B)       
        if(!userAdcStruct.Flag.Bit.CheckReg)
        {
            LOG("read reg start:");
            userAdcStruct.Flag.Bit.CheckReg = 1;
            for(uint8_t i=0;i < 7;i++)
            {
                readAdcValue = 0;
                AFE_ReadReg(i,1,(uint8_t*)&readAdcValue);
                LOG("Reg%d = %02x\n",i,readAdcValue);
            }
        }
#endif
        CS_RegisterADTrage();
    }
}
/**
 * @brief  查找中位值
 * @param  buff         数组指针
 * @param  buffLen      数组长度，长度不能大于32
 * @return uint32_t     返回查找到数组中位值
 */
uint32_t medianFilter(const uint32_t* buff,uint8_t buffLen,uint8_t index)
{
    uint32_t FindFlag = 0;
    uint32_t MidValue = 0;
    uint8_t mackIndex = 0;
    uint8_t j = 0;
    if(index > buffLen)
        index = buffLen;
    for(uint8_t i = 0;i < index ; i++)
    {
        MidValue = 0;
        MidValue --;      //undata max
        for( j = 0;j < buffLen ; j++)
        {
            if(!((FindFlag>>j)&0x01) && (MidValue >= buff[j]))
            {
                MidValue = buff[j];
                mackIndex = j;
            }
        }
        FindFlag |= (0x01 << mackIndex);
    }
    return MidValue;
}

/**
 * @brief  去除最大最小值求平均值
 * @param  buff         数组指针
 * @param  buffLen      数组长度，长度不能大于32
 * @return uint32_t     返回查找到数组中位值
 */
uint32_t WithoutMinMaxAverage(const uint32_t* buff,uint8_t buffLen)
{
    uint64_t SumAdc = 0;
    uint32_t BigAdc = 0;
    uint32_t MinAdc = 0;
    MinAdc --;                  //Unit max
    for(uint8_t i = 0;i < buffLen ; i++)
    {
        if(MinAdc >  buff[i])
            MinAdc = buff[i];
        if(BigAdc < buff[i])
            BigAdc = buff[i];
        SumAdc += buff[i];
    }
    SumAdc -= MinAdc;
    SumAdc -= BigAdc;
    return SumAdc/(buffLen-2);
}

void updateBufferValue(AdcBuff_t* buffer,uint32_t value,uint8_t bufferMax,int8_t updateTimes)
{
    if(updateTimes < 0)
        updateTimes = bufferMax;
    for(uint8_t i = 0;i < updateTimes;i++)
    {
        buffer->adcBuff[buffer->index]  = value;
        buffer->index++;
        if(buffer->index >= bufferMax)
            buffer->index = 0;
    }
}

void adc_median_filter(void)
{
    static  uint32_t lastFilterAdc = 0;
    static  uint32_t TragRestFilterAdc = 0;
    static uint8_t StableCnt = 0;
    // static uint8_t BigLoadCnt = 0;
    // static uint32_t LockedSum = 0;
    // static uint8_t LockSumCnt = 0;
    static uint8_t positiveCnt = 0,negtiveCnt = 0;
    uint32_t subAdc = 0;
    uint32_t stable_range = 0;
    adcFilterFlag_t filterFlag = {
        .Byte = 0,
    };

	userAdcStruct.Flag.Bit.SampleNew = false;
    userAdcStruct.Flag.Bit.lock = false;
    if(!userAdcStruct.Flag.Bit.adcNew)
        return;                                     // adc not ready
    userAdcStruct.Flag.Bit.adcNew = false;
    if(userAdcStruct.Flag.Bit.disableSample)
    {
        return;
    }
    if(userAdcStruct.Flag.Bit.resetFilter)
    {
        userAdcStruct.Flag.Bit.resetFilter = false;
        userAdcStruct.Flag.Bit.locked = false;
        userAdcStruct.Flag.Bit.midleFilter = true;
        StableCnt = 0;
        updateBufferValue(&AdcBuff,userAdcStruct.Adc,MID_BUF_NUM,MID_BUF_NUM-2);
    }else{
        subAdc = userAdcStruct.Adc - lastFilterAdc;
        if(subAdc > 0x80000000)
        {
            subAdc = (0 - subAdc);
        }
        if(userAdcStruct.Flag.Bit.locked)
            stable_range = ScaleWeight.DivisionAdc*20;      //0.5D*20 = 10D
        else
            stable_range = ScaleWeight.DivisionAdc*12;      //12*0.5D = 6D
        if(subAdc > stable_range)
            updateBufferValue(&AdcBuff,userAdcStruct.Adc,MID_BUF_NUM,3);        //加快显示
        else
            updateBufferValue(&AdcBuff,userAdcStruct.Adc,MID_BUF_NUM,1);
    }
    // subAdc = userAdcStruct.Adc - lastFilterAdc;
    if(userAdcStruct.Flag.Bit.midleFilter)  //中位值滤波
    {
        // userAdcStruct.FilterAdc = medianFilter(AdcBuff.adcBuff,MID_BUF_NUM,(MID_BUF_NUM+1)>>1);
        userAdcStruct.FilterAdc = WithoutMinMaxAverage(AdcBuff.adcBuff,MID_BUF_NUM);
    }else{                                  //均值滤波
        userAdcStruct.FilterAdc = WithoutMinMaxAverage(AdcBuff.adcBuff,MID_BUF_NUM);
    }
    userAdcStruct.Flag.Bit.SampleNew = TRUE;
    subAdc = userAdcStruct.FilterAdc - lastFilterAdc;
    if(subAdc > 0x80000000)
    {
        subAdc = (0 - subAdc);
        // if(subAdc > ScaleWeight.DivisionAdc)
        //     negtiveCnt++;
        // positiveCnt = 0;
    }
    // else{
    //     // negtiveCnt = 0;
    //     // if(subAdc > ScaleWeight.DivisionAdc)
    //     //     positiveCnt++;
    // }
    // if(positiveCnt > 5 || negtiveCnt > 5)
    // {
    //     userAdcStruct.Flag.Bit.locked = false;
    //     userAdcStruct.Flag.Bit.midleFilter = TRUE;      //多次 同方向重量变化后切换中位值 快速响应
    //     userAdcStruct.Flag.Bit.resetFilter = TRUE;      //重置一下加快响应，同时消除可能出现的加重重量减少       
    // }

    stable_range = ScaleWeight.DivisionAdc*3;              //0.5d*3 = 1.5D
    StableCnt ++;
    if(subAdc <= stable_range)
    {
        if(StableCnt > 7)
        {
            StableCnt = 0;
            userAdcStruct.Flag.Bit.lock = true;
            userAdcStruct.Flag.Bit.locked = true;
            userAdcStruct.Flag.Bit.midleFilter = false;             //稳定后关闭中位值滤波，启用滑动均值滤波
            // LOG("lock Sample=%X\n",userAdcStruct.FilterAdc);
        }
    }else{
        StableCnt = 0;
        if(subAdc >= (stable_range*4))
        {
            userAdcStruct.Flag.Bit.locked = false;
            userAdcStruct.Flag.Bit.midleFilter = TRUE;             //开启中位值滤波
            updateBufferValue(&AdcBuff,userAdcStruct.Adc,MID_BUF_NUM,MID_BUF_NUM>>1+2);
        }
    }
    {
        stable_range = ScaleWeight.DivisionAdc*2*7/10;            // 0.5D*2*7/10 = 0.7D
        if(userAdcStruct.Flag.Bit.AtuoStartRest)
        {
            subAdc = userAdcStruct.FilterAdc - TragRestFilterAdc;
            filterFlag.Bit.subNegtiv = false;
            if(subAdc > 0x80000000)
            {
                subAdc = 0 - subAdc;
                filterFlag.Bit.subNegtiv = TRUE;
            }
            if(subAdc > stable_range)
            {
                if(filterFlag.Bit.subNegtiv)
                {
                    negtiveCnt++;
                    positiveCnt = 0;
                }else{
                    negtiveCnt = 0;
                    positiveCnt++;
                }
                if(positiveCnt > 5 || negtiveCnt > 5)
                {
                    // userAdcStruct.Flag.Bit.locked = false;
                    userAdcStruct.Flag.Bit.AtuoStartRest = false;
                    // LOG("rest cnt p=%X,n=%X\n",positiveCnt,negtiveCnt);
                    updateBufferValue(&AdcBuff,userAdcStruct.Adc,MID_BUF_NUM,MID_BUF_NUM>>1+2);
                    // userAdcStruct.Flag.Bit.midleFilter = TRUE;      //多次 同方向重量变化后切换中位值 快速响应
                    // userAdcStruct.Flag.Bit.resetFilter = TRUE;      //重置一下加快响应，同时消除可能出现的加重重量减少    
                }
            }else{
                userAdcStruct.Flag.Bit.AtuoStartRest = false;
            }
        }else{
            if(subAdc > stable_range)
            {
                userAdcStruct.Flag.Bit.AtuoStartRest = TRUE;
                TragRestFilterAdc = lastFilterAdc;
                negtiveCnt = 0;
                positiveCnt = 0;
            }
        }
    }
    lastFilterAdc = userAdcStruct.FilterAdc;

#define  LAST_PERSENT   90
    if(!userAdcStruct.Flag.Bit.disableSample)
    {
        if(userAdcStruct.Flag.Bit.locked && ScaleWeight.Flag.Bit.Load)
        {
            userAdcStruct.DisplayAdc *= LAST_PERSENT;
            userAdcStruct.DisplayAdc += userAdcStruct.FilterAdc *(100-LAST_PERSENT);
            userAdcStruct.DisplayAdc /= 100;
        }else{
            userAdcStruct.DisplayAdc = userAdcStruct.FilterAdc;
        }
    }else{
        // userAdcStruct.Flag.Bit.SampleNew = false;
        userAdcStruct.Flag.Bit.lock = false;                //按键期间禁止锁定
    }
    // if(userAdcStruct.Flag.Bit.locked)
    // {
    //     if(LockSumCnt == (0x08-2))
    //     {
    //         LockedSum >>= 1;
    //         LockSumCnt>>= 1;
    //     }
    //     LockSumCnt++;
    //     LockedSum += userAdcStruct.FilterAdc;
    //     userAdcStruct.FilterAdc = LockedSum/LockSumCnt;
    //     if(subAdc > (stable_range >> 1))                //超过 0.5d*3*2 = 30d
    //     {
    //         userAdcStruct.Flag.Bit.locked = false;
    //         if(subAdc > (stable_range >> 2))            //超过 0.5d*3*4 = 60d
    //         {
    //             userAdcStruct.Flag.Bit.resetFilter = TRUE;
    //         }
    //         userAdcStruct.Flag.Bit.midleFilter = TRUE;  //切换中位值 快速响应
    //     }
    // }else{
    //     LockedSum = 0;
    //     LockSumCnt = 0;
    // }
    // LOG("filter Sample=%X,lock cnt = %d\n",userAdcStruct.FilterAdc,LockSumCnt);
    // LOG("orign adc=%x,filterAdc=%x\r\n",userAdcStruct.Adc,userAdcStruct.FilterAdc);
}


WaterFlow_t  waterFlow;
#define      OUT_RANGE_WATER_MinD           1           //0.5g
#define      IN_RANGE_WATER_TIMED           8           //0.5*8   = 4g
#define      OUT_RANGE_WATER_TIMED          100         //100*0.5 = 50g
void  F_DetctiveWaterFlow(void)
{
    int32_t subAdc = 0;
    uint8_t temp = ADD_WATER;
    if(!userAdcStruct.Flag.Bit.SampleNew)
    {
        return;
    }
    subAdc = waterFlow.lastFiltAdc - userAdcStruct.FilterAdc;
    // subAdc = waterFlow.lastFiltAdc - userAdcStruct.Adc;
    waterFlow.Flag.Bit.StopTrage = false;
    // LOG("waterFadc=%d\r\n",userAdcStruct.FilterAdc);
    if(subAdc < 0)
    {
        temp = ADD_WATER;
        subAdc = 0 - subAdc;
    }else{
        temp = SUB_WATER;
    }
    if(temp != waterFlow.WaterType)
    {
        waterFlow.stopCnt = 0;
        waterFlow.MidleCnt = 0;
        waterFlow.litterCnt = 0;
        waterFlow.BigCnt = 0;
    }
    waterFlow.WaterType = temp;

    if(subAdc > ScaleWeight.DivisionAdc)        //0.5g
    {
        if(subAdc > ScaleWeight.DivisionAdc*OUT_RANGE_WATER_TIMED)      //rash weight over range not water
        {
            if(!waterFlow.Flag.Bit.WaterFlowIng)
                waterFlow.Flag.Bit.StopTrage = 1;
            waterFlow.BigCnt++;
        }else{                                                          //weight change in range
            waterFlow.BigCnt = 0;
            // if(temp != waterFlow.WaterType)
            //     waterFlow.Flag.Bit.WaterFlowRest = true;
            // else{
                if(subAdc > ScaleWeight.DivisionAdc*IN_RANGE_WATER_TIMED)   //中水流计数
                {
                    waterFlow.MidleCnt ++;
                    if(waterFlow.MidleCnt > 2)
                        waterFlow.litterCnt = 0;
                    if(waterFlow.MidleCnt > 3){
                        waterFlow.Flag.Bit.WaterFlowIng = TRUE;             //水流启动
                        LOG("midle water flow ing\r\n");
                    }
                }else{                                                      //小水流计数
                    waterFlow.litterCnt++;
                    if(waterFlow.litterCnt > 2)
                        waterFlow.MidleCnt = 0;
                    if(waterFlow.litterCnt > 5)
                    {
                        waterFlow.Flag.Bit.WaterFlowIng = TRUE;             //水流启动
                        LOG("litter water flow ing\r\n");
                    }
                }                
            // }
        }        
    }else{
        waterFlow.BigCnt = 0;
        waterFlow.Flag.Bit.StopTrage = 1;
    }
    if(waterFlow.Flag.Bit.StopTrage)
    {
        waterFlow.stopCnt++;
        if(waterFlow.stopCnt > 5 && waterFlow.BigCnt < 4)
        {
            waterFlow.Flag.Bit.WaterFlowRest = true;
            waterFlow.WaterType = 0;
        }else{
            if(waterFlow.BigCnt > 6)
            {
                waterFlow.Flag.Bit.WaterFlowIng = TRUE;             //水流启动
                LOG("contiue big water flow ing\r\n");
            }
        }
    }
    if(waterFlow.Flag.Bit.WaterFlowRest)
    {
        waterFlow.Flag.Byte = 0;
        waterFlow.stopCnt = 0;
        waterFlow.MidleCnt = 0;
        waterFlow.litterCnt = 0;
        waterFlow.BigCnt = 0;
    }
    waterFlow.lastFiltAdc = userAdcStruct.FilterAdc;
}

/**
 * @brief  判断水流是否即将开始
 * @return true 
 * @return false 
 */
bool JudgeWaterOnRoad(void)
{
    bool waterOnRoad = FALSE;
    if(waterFlow.litterCnt > 3)
        waterOnRoad = TRUE;
    if(waterFlow.MidleCnt > 1)
        waterOnRoad = TRUE;
    return waterOnRoad;
}


